/**
 * 
 */
package info.niwota.group;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.provider.Contacts;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * @author qiangli
 * 
 */
public class ContactListAdapter extends BaseAdapter {
	private class ContactContentObserver extends ContentObserver {

		public ContactContentObserver(Handler handler) {
			super(handler);
		}

		@Override
		public boolean deliverSelfNotifications() {
			return true;
		}

		@Override
		public void onChange(boolean selfChange) {
			if (Constants.DEBUG_ENABLED) {
				Log.d(TAG, "onChange: self: " + selfChange);
			}
			invalidate();
		}

	}

	private class LoadTask extends AsyncTask<Void, Void, List<EmailContact>> {

		private EtalkContactsActivity ctx;

		public LoadTask(EtalkContactsActivity ctx) {
			this.ctx = ctx;
		}

		@Override
		protected List<EmailContact> doInBackground(Void... params) {
			if (Constants.DEBUG_ENABLED) {
				Log.d(TAG, "doInBackground refresh: " + reload);
			}
			//
			if (reload) {
				try {
					List<EmailContact> c = new ArrayList<EmailContact> ();
					ContactUtils.loadContacts(ctx, c);
					//
					sortContacts(c);
					//
					return c;
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			return null;
		}

		@Override
		protected void onCancelled() {
			dismissProgress(ctx);
		}

		@Override
		protected void onPostExecute(List<EmailContact> result) {
			try {
				if (result != null) {
					setContacts(result);
					//
					result.clear();
					notifyDataSetChanged();
					taskDone(ctx);
				}
			} finally {
				reload = false;
				dismissProgress(ctx);
			}
		}

		@Override
		protected void onPreExecute() {
			showProgress(ctx);
		}
	}

	private class SortTask extends AsyncTask<Void, Void, Void> {
		private EtalkContactsActivity ctx;

		public SortTask(EtalkContactsActivity ctx) {
			this.ctx = ctx;
		}

		@Override
		protected Void doInBackground(Void... params) {
			sortContacts(getContacts());
			return null;
		}

		@Override
		protected void onCancelled() {
			dismissProgress(ctx);
		}

		@Override
		protected void onPostExecute(Void arg) {
			try {
				notifyDataSetChanged();
				taskDone(ctx);
			} finally {
				dismissProgress(ctx);
			}
		}

		@Override
		protected void onPreExecute() {
			showProgress(ctx);
		}
	}

	private static class ViewHolder {
		private TextView date;
		private TextView desc;
		private ImageView icon;
		private TextView title;
	}

	private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";

	private static final int[] drawables = { R.drawable.star_no,
			R.drawable.star_one, R.drawable.star_super };

	private static final Bitmap[] images = new Bitmap[3];

	private static boolean reload = true;

	public static final int SORT_BY_NAME = 1;

	public static final int SORT_BY_STAR = 0;

	public static final int SORT_BY_TIME = 2;
	
	private static final int SORT_DIR_ASC = 0;
	
	static final String TAG = "ContactListAdapter";

	public static void notifyChange() {
		// TODO this is a hack for now
		if (Constants.DEBUG_ENABLED) {
			Log.d(TAG, "notifyChange");
		}
		reload = true;
	}

	private ArrayList<EmailContact> contacts = new ArrayList<EmailContact>();

	private SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);

	private Handler handler = new Handler();

	private LayoutInflater inflater;

	private int sortBy = SORT_BY_STAR;
	
	private int sortDir = SORT_DIR_ASC;

	private AsyncTask<Void, Void, Void> sortTask;

	private AsyncTask<Void, Void, List<EmailContact>> loadTask;

	public ContactListAdapter() {
	}

	private void dismissProgress(EtalkContactsActivity ctx) {
		try {
			// //context.setProgressBarIndeterminateVisibility(false);
			ctx.dismissDialog(EtalkContactsActivity.DIALOG_PROGRESS_LOADING);
		} catch (Exception e) {
			//
		}
	}

	synchronized public void doSort(EtalkContactsActivity ctx, int id) {
		if (sortTask != null) {
			sortTask.cancel(true);
		}
		//
		sortDir = (sortDir == 0 ? 1 : 0); // toggle
		switch (id) {
		case R.id.byNameButton:
			sortDir = (sortBy == SORT_BY_NAME ? sortDir : 0);
			sortBy = SORT_BY_NAME;
			break;
		case R.id.byStarButton:
			sortDir = (sortBy == SORT_BY_STAR ? sortDir : 0);
			sortBy = SORT_BY_STAR;
			break;
		case R.id.byTimeButton:
			sortDir = (sortBy == SORT_BY_TIME ? sortDir : 0);
			sortBy = SORT_BY_TIME;
			break;
		}
		//
		sortTask = new SortTask(ctx).execute();
	}

	private CharSequence formatDate(long lastTime) {
		if (lastTime <= 0) {
			return "";
		}
		return formatter.format(new Date(lastTime));
	}

	public int getCount() {
		return getContacts().size();
	}

	public EmailContact getItem(int position) {
		return getContacts().get(position);
	}

	public long getItemId(int position) {
		return position;
	}

	public int getSortBy() {
		return sortBy;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder;
		if (convertView == null) {
			convertView = inflater.inflate(R.layout.list_item2, null);
			holder = new ViewHolder();
			holder.title = (TextView) convertView
					.findViewById(R.id.list_item2_title);
			holder.date = (TextView) convertView
					.findViewById(R.id.list_item2_date);
			holder.desc = (TextView) convertView
					.findViewById(R.id.list_item2_desc);
			holder.icon = (ImageView) convertView
					.findViewById(R.id.list_item2_icon);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}
		EmailContact item = getContacts().get(position);
		holder.title.setText(item.name);
		holder.date.setText(formatDate(item.lastTime));
		holder.desc.setText(Utils.toString(item.emails));
		int star = item.getStarred();
		holder.icon.setImageBitmap(images[star]);
		return convertView;
	}

	public void init(Context ctx) {
		inflater = LayoutInflater.from(ctx);
		for (int i = 0; i < drawables.length; i++) {
			images[i] = BitmapFactory.decodeResource(ctx.getResources(),
					drawables[i]);
		}
		reload = true; // first time initialization
		//
		registerContentObservers(ctx);
	}

	public void initContacts(EtalkContactsActivity ctx) {
		doLoad(ctx);
	}

	public void invalidate() {
		reload = true;
	}

	public void refresh() {
		notifyDataSetChanged();
	}

	private void registerContentObservers(Context ctx) {
		ContentResolver cr = ctx.getContentResolver();
		ContactContentObserver co = new ContactContentObserver(handler);
		cr.registerContentObserver(Contacts.CONTENT_URI, true, co);
		cr.registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true,
				co);
	}

	public void reload(EtalkContactsActivity ctx) {
		doLoad(ctx);
	}

	private void doLoad(EtalkContactsActivity ctx) {
		if (loadTask != null) {
			loadTask.cancel(true);
		}
		loadTask = new LoadTask(ctx).execute();
	}

	public void restoreSortSettings(EtalkContactsActivity ctx) {
		sortBy = Preferences.getSortBy(ctx, SORT_BY_STAR);
		sortDir = Preferences.getSortDir(ctx, SORT_DIR_ASC);
	}

	public void saveSortSettings(EtalkContactsActivity ctx) {
		Preferences.putSortBy(ctx, sortBy);
		Preferences.putSortDir(ctx, sortDir);
	}

	private void showProgress(EtalkContactsActivity ctx) {
		try {
			ctx.showDialog(EtalkContactsActivity.DIALOG_PROGRESS_LOADING);
		} catch (Exception e) {
			//
		}
	}

	private void sortContacts(List<EmailContact> c) {
		Collections.sort(c, new Comparator<EmailContact>() {
			public int compare(EmailContact o1, EmailContact o2) {
				int n = o1.name.compareTo(o2.name);
				switch (sortBy) {
				case SORT_BY_NAME:
					break;
				case SORT_BY_STAR:
					n = (o1.starred == o2.starred ? n : o2.starred - o1.starred);
					break;
				case SORT_BY_TIME:
					n = (o1.lastTime == o2.lastTime ? n
							: (o1.lastTime > o2.lastTime ? -1 : 1));
					break;
				}
				return (sortDir == 0 ? n : -n);
			}
		});
	}

	private void taskDone(EtalkContactsActivity ctx) {
		boolean show = ((sortBy == SORT_BY_NAME || sortBy == SORT_BY_STAR) && getContacts()
				.size() > NameIndex.PAGESIZE);
		ctx.showCompass(show);
	}

	public List<EmailContact> getContacts() {
		synchronized(contacts) {
			return contacts;
		}
	}
	
	public void setContacts(List<EmailContact> result) {
		synchronized(contacts) {
			contacts.clear();
			contacts.addAll(result);
		}
	}
}
